library(readxl)
setwd("/Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/tables")
path <- read_excel("metabolic_pathways_mastitis_2023.xlsx", sheet = "taxonomy_path")
path_ig <- read_excel("metabolic_pathways_mastitis_2023.xlsx", sheet = "taxonomy_ig")
pathways <- merge(path, path_ig, all.x=T, by=c("Pathway", "Description"))
write.csv(pathways, row.names = F, "/Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/tables/pathways_tax.csv")

##Importing tables

Warning: The working directory was changed to /Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/tables inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.

Aglomerating pathways at the Subclass level

physeq_subclass <- tax_glom(physeq_pathways, taxrank = "Subclass")

Converting phyloseq object to dataframe

write.csv(mean_pathways, "/Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/tables/mean_pathways.csv", row.names = F)

converting dataframe to matrix

library(tibble)
path_subclass_mx <- physeq_subclass_df %>% select(sample_ID, Subclass, Abundance) %>% pivot_wider(names_from = Subclass, values_from = Abundance) %>% select(-UNMAPPED,-UNINTEGRATED) %>% column_to_rownames("sample_ID") %>% as.matrix()

Annotations for Heatmap

library(pheatmap)
library(viridis) #color pallet, it's optional
library(RColorBrewer)

#HEATMAP RA USING ln color pallet RBrewer
heatmap <- pheatmap(
  mat               = t(log10(path_subclass_mx+1)),
  border_color      = NA,
  show_colnames     = F,
  show_rownames     = T,
  angle_col = 90,
#  drop_levels       = TRUE,
 # fontsize_col = 4,
 fontsize_row = 5,
#  fontsize          = 14,
 # color             = brewer.pal(9,"RdYlBu"),
#color = inferno(100),  
#number_color = NA,
 annotation_col = annotation_samples,
  annotation_colors = anno_color,
  annotation_names_col = F,
  annotation_names_row = F,
  cluster_cols = T,
  cluster_rows = T,
 clustering_method = "ward.D2",
  gaps_row = FALSE,
)
heatmap

library(ggplot2)
setwd("/Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/figures")
ggsave(plot=heatmap, "heatmap_pathways_mastitis.png", width = 10, height = 5)

Differential abundance analyses

Aggregate phyloseq objects by time points

physeq_day1_week1 <- subset_samples(physeq_subclass, Time_tx%in%c("Day -1","Week 1"))
physeq_day1_week9 <- subset_samples(physeq_subclass, Time_tx%in%c("Day -1","Week 9"))
physeq_day1_week5 <- subset_samples(physeq_subclass, Time_tx%in%c("Day -1","Week 5"))
physeq_week9_5 <- subset_samples(physeq_subclass, Time_tx%in%c("Week 9","Week 1"))
physeq_week9_1 <- subset_samples(physeq_subclass, Time_tx%in%c("Week 9","Week 5"))

Aggregate phyloseq objects by time points

physeq_day1 <- subset_samples(physeq_subclass, Time_tx%in%"Day -1")
physeq_week1 <- subset_samples(physeq_subclass, Time_tx%in%c("Week 1"))
physeq_week5 <- subset_samples(physeq_subclass, Time_tx%in%c("Week 5"))
physeq_week9 <- subset_samples(physeq_subclass, Time_tx%in%c("Week 9"))

Day 0 (other time points were done in the same way)

physeq <- physeq_week5

MaAsLin2

Aglomerating pathways at the Subclass level

physeq_path <- tax_glom(physeq_pathways, taxrank = "Description")
library(microbial)
rf_time <- biomarker(physeq=physeq_path, group = "Time_tx", normalize = F)

Call:
 randomForest(formula = group ~ ., data = data, importance = TRUE,      proximity = TRUE, ntree = ntree) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 12

        OOB estimate of  error rate: 38.36%
Confusion matrix:
       Day -1 Week 1 Week 5 Week 9 class.error
Day -1     30      7      1      2   0.2500000
Week 1      2     23     12      3   0.4250000
Week 5      1     11     22      6   0.4500000
Week 9      7      1      8     23   0.4102564
rf_time
rf_time %>% head(n=25) %>% ggbarplot(y="Value",x="Description"
                                     #, fill = "Class", palette = "simpsons"
                                     ) + theme(axis.text.x = element_text(angle = 90, hjust = 1))

Converting phyloseq object to dataframe

physeq_df <- psmelt(physeq_path)
top25 <- rf_time %>% head(n=25)
mean <- physeq_df %>% group_by(Description) %>% summarise(Average = mean(Abundance))

order <- physeq_df %>% filter(Description %in% top25$Description) %>% merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% group_by(Time_tx, Description) %>% summarise(top = mean(FC)) %>% filter(Time_tx=="Day -1") %>% arrange(top)

top_25_plot <- physeq_df %>% filter(Description %in% top25$Description) %>% merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% 
  ggbarplot(x="Description",y="FC", fill="Time_tx", palette = c("#FFD700", "#008000", "#0073C2ff", "#800080"),
            add = c("mean_ci"), position = position_dodge(width = 0.7), orientation="horiz", xlab = "", ylab = "Fold change (mean)",
            #facet.by = "Class",
            order = order$Description)
top_25_plot
library(ggplot2)
setwd("/Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/figures")
ggsave(plot=top_25_plot, "top25_rf_pathways_mastitis.png", width = 10, height = 8)

Treatment plot

physeq_day1 <- subset_samples(physeq_path, Time_tx%in%c("Day -1"))
physeq_week1 <- subset_samples(physeq_path, Time_tx%in%c("Week 1"))
physeq_week5 <- subset_samples(physeq_path, Time_tx%in%c("Week 5"))
physeq_week9 <- subset_samples(physeq_path, Time_tx%in%c("Week 9"))
library(microbial)
rf_treatment <- biomarker(physeq=physeq_week9, group = "Treatment", normalize = F)

Call:
 randomForest(formula = group ~ ., data = data, importance = TRUE,      proximity = TRUE, ntree = ntree) 
               Type of random forest: classification
                     Number of trees: 500
No. of variables tried at each split: 3

        OOB estimate of  error rate: 20.51%
Confusion matrix:
           Antibiotic Control class.error
Antibiotic         15       4   0.2105263
Control             4      16   0.2000000
rf_treatment
rf_treatment %>% head(n=25) %>% ggbarplot(y="Value",x="Description"
                                     #, fill = "Class", palette = "simpsons"
                                     ) + theme(axis.text.x = element_text(angle = 90, hjust = 1))

top25 <- rf_treatment %>% head(n=25)
mean <- physeq_df %>% filter(Time_tx=="Week 5") %>% group_by(Description) %>% summarise(Average = mean(Abundance))

order <- physeq_df %>% filter(Description %in% top25$Description, Time_tx=="Week 5") %>% merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% group_by(Treatment, Description) %>% summarise(top = mean(FC)) %>% filter(Treatment=="Control") %>% arrange(top)
`summarise()` has grouped output by 'Treatment'. You can override using the `.groups` argument.
top_25_w5_plot <- physeq_df %>% 
  filter(Description %in% top25$Description, Time_tx=="Week 5") %>% 
  merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% 
  ggbarplot(x="Description", y="FC", fill="Treatment", palette = "npg",
            add = c("mean_ci"), position = position_dodge(width = 0.7), 
            orientation="horiz", xlab = "", ylab = "Fold change (mean)",
            facet.by = "Time_tx",
            order = order$Description
            )
top_25_w5_plot

physeq_df %>% 
  filter(Description %in% top25$Description, Time_tx=="Week 9") %>% 
  group_by(Description) %>% 
  wilcox_test(Abundance ~ Treatment, paired = F, alternative = "less") %>% 
  add_significance()
physeq_df %>% 
  filter(Description %in% top25$Description, Time_tx=="Week 9") %>% 
  group_by(Description) %>% 
  wilcox_test(Abundance ~ Treatment, paired = F, alternative = "greater") %>% 
  add_significance()
top25 <- rf_treatment %>% head(n=25)
mean <- physeq_df %>% filter(Time_tx=="Week 9") %>% group_by(Description) %>% summarise(Average = mean(Abundance))

order <- physeq_df %>% filter(Description %in% top25$Description, Time_tx=="Week 9") %>% merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% group_by(Treatment, Description) %>% summarise(top = mean(FC)) %>% filter(Treatment=="Control") %>% arrange(top)
`summarise()` has grouped output by 'Treatment'. You can override using the `.groups` argument.
top_25_w9_plot <- physeq_df %>% 
  filter(Description %in% top25$Description, Time_tx=="Week 9") %>% 
  merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% 
  ggbarplot(x="Description", y="FC", fill="Treatment", palette = "npg",
            add = c("mean_ci"), position = position_dodge(width = 0.7), 
            orientation="horiz", xlab = "", ylab = "Fold change (mean)",
            facet.by = "Time_tx",
            order = order$Description
            )
top_25_w9_plot

top25 <- rf_treatment %>% head(n=25)
mean <- physeq_df %>% filter(Time_tx=="Day -1") %>% group_by(Description) %>% summarise(Average = mean(Abundance))

order <- physeq_df %>% filter(Description %in% top25$Description, Time_tx=="Day -1") %>% merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% group_by(Treatment, Description) %>% summarise(top = mean(FC)) %>% filter(Treatment=="Antibiotic") %>% arrange(top)

top_25_d1_plot <- physeq_df %>% 
  filter(Description %in% top25$Description, Time_tx=="Day -1") %>% 
  merge(mean, by="Description") %>% mutate(FC=Abundance/Average) %>% 
  ggbarplot(x="Description", y="FC", fill="Treatment", palette = "npg",
            add = c("mean_ci"), position = position_dodge(width = 0.7), 
            orientation="horiz", xlab = "", ylab = "Fold change (mean)",
            #facet.by = "Class",
            order = order$Description
            )
top_25_d1_plot
w5_w9_diff_plots <- ggarrange(top_25_w5_plot, top_25_w9_plot, labels = c("A","B"), nrow=1, common.legend = T)
w5_w9_diff_plots
library(ggplot2)
setwd("/Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/figures")
Warning: The working directory was changed to /Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/figures inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
ggsave(plot=w5_w9_diff_plots, "top25_rf_metabolicpaths_mastitis.png", width = 20, height = 8)

Pathways differential

path_diff_plots <- ggarrange(top_25_w1_plot,top_25_w5_plot, top_25_w9_plot, labels = c("A","B","C"), nrow=1, common.legend = T)
path_diff_plots

library(ggplot2)
setwd("/Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/figures")
Warning: The working directory was changed to /Users/karlavasco/Library/CloudStorage/OneDrive-MichiganStateUniversity/Manning_lab/Metabolomics_mastitis/figures inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
ggsave(plot=path_diff_plots, "top_rf_metabolicpaths_mastitis.png", width = 24, height = 8)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkocmVhZHhsKQpzZXR3ZCgiL1VzZXJzL2thcmxhdmFzY28vTGlicmFyeS9DbG91ZFN0b3JhZ2UvT25lRHJpdmUtTWljaGlnYW5TdGF0ZVVuaXZlcnNpdHkvTWFubmluZ19sYWIvTWV0YWJvbG9taWNzX21hc3RpdGlzL3RhYmxlcyIpCnBhdGggPC0gcmVhZF9leGNlbCgibWV0YWJvbGljX3BhdGh3YXlzX21hc3RpdGlzXzIwMjMueGxzeCIsIHNoZWV0ID0gInRheG9ub215X3BhdGgiKQpwYXRoX2lnIDwtIHJlYWRfZXhjZWwoIm1ldGFib2xpY19wYXRod2F5c19tYXN0aXRpc18yMDIzLnhsc3giLCBzaGVldCA9ICJ0YXhvbm9teV9pZyIpCgpgYGAKCmBgYHtyfQpwYXRod2F5cyA8LSBtZXJnZShwYXRoLCBwYXRoX2lnLCBhbGwueD1ULCBieT1jKCJQYXRod2F5IiwgIkRlc2NyaXB0aW9uIikpCmBgYAoKYGBge3J9CndyaXRlLmNzdihwYXRod2F5cywgcm93Lm5hbWVzID0gRiwgIi9Vc2Vycy9rYXJsYXZhc2NvL0xpYnJhcnkvQ2xvdWRTdG9yYWdlL09uZURyaXZlLU1pY2hpZ2FuU3RhdGVVbml2ZXJzaXR5L01hbm5pbmdfbGFiL01ldGFib2xvbWljc19tYXN0aXRpcy90YWJsZXMvcGF0aHdheXNfdGF4LmNzdiIpCmBgYAoKIyNJbXBvcnRpbmcgdGFibGVzCmBgYHtyIGVjaG8gPSBGQUxTRX0KbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkeGwpCgpzZXR3ZCgiL1VzZXJzL2thcmxhdmFzY28vTGlicmFyeS9DbG91ZFN0b3JhZ2UvT25lRHJpdmUtTWljaGlnYW5TdGF0ZVVuaXZlcnNpdHkvTWFubmluZ19sYWIvTWV0YWJvbG9taWNzX21hc3RpdGlzL3RhYmxlcyIpCgojcmVhZCBpbiBvdHUgdGFibGUKb3R1X3RhYmxlID0gcmVhZF9leGNlbCgibWV0YWJvbGljX3BhdGh3YXlzX21hc3RpdGlzXzIwMjMueGxzeCIsIHNoZWV0PSJodW1hbm5fcGF0aGFidW5kYW5jZV9yZWxhYiIpCgpsaWJyYXJ5KHRpYmJsZSkKb3R1X3RhYmxlIDwtIG90dV90YWJsZSAlPiUgcmVtb3ZlX3Jvd25hbWVzICU+JSBjb2x1bW5fdG9fcm93bmFtZXModmFyPSJPVFVfSUQiKQpvdHVfdGFibGU9YXMubWF0cml4KG90dV90YWJsZSkKb3R1X3RhYmxlIDwtIG90dV90YWJsZQojbW9kZShvdHVfdGFibGUpIDwtICJpbnRlZ2VyIgoKI3JlYWQgaW4gdGF4b25vbXkKdGF4b25vbXkgPSByZWFkX2V4Y2VsKCJtZXRhYm9saWNfcGF0aHdheXNfbWFzdGl0aXNfMjAyMy54bHN4Iiwgc2hlZXQ9InRheG9ub215X3BhdGh3YXlzIikKdGF4b25vbXkgPC0gdGF4b25vbXkgJT4lIHJlbW92ZV9yb3duYW1lcyAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKHZhcj0iT1RVX0lEIikKdGF4b25vbXk9YXMubWF0cml4KHRheG9ub215KQoKI3JlYWQgaW4gbWV0YWRhdGEKbWV0YWRhdGEgPC0gcmVhZF9leGNlbCgibWV0YWJvbGljX3BhdGh3YXlzX21hc3RpdGlzXzIwMjMueGxzeCIsIHNoZWV0ID0gIm1ldGFkYXRhIikKbWV0YWRhdGEgPC0gbWV0YWRhdGEgJT4lIHJlbW92ZV9yb3duYW1lcyAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKHZhcj0ic2VxdWVuY2VfaWQiKQoKbGlicmFyeSgicGh5bG9zZXEiKQoKI2ltcG9ydCBhcyBwaHlsb3NlcSBvYmplY3RzCk9UVSA9IG90dV90YWJsZShvdHVfdGFibGUsdGF4YV9hcmVfcm93cz1UUlVFKQpUQVggPSB0YXhfdGFibGUodGF4b25vbXkpCk1FVEEgPSBzYW1wbGVfZGF0YShtZXRhZGF0YSkKCiNGaW5hbCBwaHlsb3NlcSBvdXRwdXQgaXMgbmFtZWQgYXMgcGh5c2VxCnBoeXNlcV9wYXRod2F5cz1waHlsb3NlcShPVFUsVEFYLE1FVEEpCmBgYAoKIyBBZ2xvbWVyYXRpbmcgcGF0aHdheXMgYXQgdGhlIFN1YmNsYXNzIGxldmVsCmBgYHtyfQpwaHlzZXFfc3ViY2xhc3MgPC0gdGF4X2dsb20ocGh5c2VxX3BhdGh3YXlzLCB0YXhyYW5rID0gIlN1YmNsYXNzIikKYGBgCgojIENvbnZlcnRpbmcgcGh5bG9zZXEgb2JqZWN0IHRvIGRhdGFmcmFtZQpgYGB7cn0KcGh5c2VxX3N1YmNsYXNzX2RmIDwtIHBzbWVsdChwaHlzZXFfc3ViY2xhc3MpCmBgYApgYGB7cn0KbWVhbl9wYXRod2F5cyA8LSBwaHlzZXFfcGF0aHdheXMgJT4lIHBzbWVsdCgpICU+JSAKICBncm91cF9ieShUcmVhdG1lbnQsIFRpbWVfdHgsIENsYXNzLCBTdWJjbGFzcywgUGF0aHdheSwgRGVzY3JpcHRpb24pICU+JSAKICBzdW1tYXJpc2UoQXZlcmFnZSA9IG1lYW4oQWJ1bmRhbmNlKSkKYGBgCgpgYGB7cn0Kd3JpdGUuY3N2KG1lYW5fcGF0aHdheXMsICIvVXNlcnMva2FybGF2YXNjby9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1NaWNoaWdhblN0YXRlVW5pdmVyc2l0eS9NYW5uaW5nX2xhYi9NZXRhYm9sb21pY3NfbWFzdGl0aXMvdGFibGVzL21lYW5fcGF0aHdheXMuY3N2Iiwgcm93Lm5hbWVzID0gRikKYGBgCgojIGNvbnZlcnRpbmcgZGF0YWZyYW1lIHRvIG1hdHJpeCAKYGBge3J9CmxpYnJhcnkodGliYmxlKQpwYXRoX3N1YmNsYXNzX214IDwtIHBoeXNlcV9zdWJjbGFzc19kZiAlPiUgc2VsZWN0KHNhbXBsZV9JRCwgU3ViY2xhc3MsIEFidW5kYW5jZSkgJT4lIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBTdWJjbGFzcywgdmFsdWVzX2Zyb20gPSBBYnVuZGFuY2UpICU+JSBzZWxlY3QoLVVOTUFQUEVELC1VTklOVEVHUkFURUQpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoInNhbXBsZV9JRCIpICU+JSBhcy5tYXRyaXgoKQpgYGAKCiMgQW5ub3RhdGlvbnMgZm9yIEhlYXRtYXAKYGBge3J9CmxpYnJhcnkoZHBseXIpCmFubm90YXRpb25fc2FtcGxlcyA8LSBwaHlzZXFfc3ViY2xhc3NfZGYgJT4lIAogIGRwbHlyOjpzZWxlY3Qoc2FtcGxlX0lELCBUcmVhdG1lbnQsIFRpbWVfdHgpICU+JSBkaXN0aW5jdCgpICU+JSAgICAKICByZW1vdmVfcm93bmFtZXMgJT4lIGNvbHVtbl90b19yb3duYW1lcyh2YXI9InNhbXBsZV9JRCIpCgoKYW5ub19jb2xvciA8LSBsaXN0KFRyZWF0bWVudCA9IGMoQ29udHJvbCA9ICIjM0I0OTkyRkYiLCBBbnRpYmlvdGljID0gIiNFRTAwMDBGRiIpLAogICAgICAgICAgICAgICAgICAgVGltZV90eCA9IGMoYERheSAtMWAgPSAiI0ZGRDcwMCIsIGBXZWVrIDFgPSAiIzAwODAwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFdlZWsgNWAgPSAiIzhhOTE5N2ZmIiwgYFdlZWsgOWA9IiM4MDAwODAiKSkKYGBgCgpgYGB7cn0KbGlicmFyeShwaGVhdG1hcCkKbGlicmFyeSh2aXJpZGlzKSAjY29sb3IgcGFsbGV0LCBpdCdzIG9wdGlvbmFsCmxpYnJhcnkoUkNvbG9yQnJld2VyKQoKI0hFQVRNQVAgUkEgVVNJTkcgbG4gY29sb3IgcGFsbGV0IFJCcmV3ZXIKaGVhdG1hcCA8LSBwaGVhdG1hcCgKICBtYXQgICAgICAgICAgICAgICA9IHQobG9nMTAocGF0aF9zdWJjbGFzc19teCsxKSksCiAgYm9yZGVyX2NvbG9yICAgICAgPSBOQSwKICBzaG93X2NvbG5hbWVzICAgICA9IEYsCiAgc2hvd19yb3duYW1lcyAgICAgPSBULAogIGFuZ2xlX2NvbCA9IDkwLAojICBkcm9wX2xldmVscyAgICAgICA9IFRSVUUsCiAjIGZvbnRzaXplX2NvbCA9IDQsCiBmb250c2l6ZV9yb3cgPSA1LAojICBmb250c2l6ZSAgICAgICAgICA9IDE0LAogIyBjb2xvciAgICAgICAgICAgICA9IGJyZXdlci5wYWwoOSwiUmRZbEJ1IiksCiNjb2xvciA9IGluZmVybm8oMTAwKSwgIAojbnVtYmVyX2NvbG9yID0gTkEsCiBhbm5vdGF0aW9uX2NvbCA9IGFubm90YXRpb25fc2FtcGxlcywKICBhbm5vdGF0aW9uX2NvbG9ycyA9IGFubm9fY29sb3IsCiAgYW5ub3RhdGlvbl9uYW1lc19jb2wgPSBGLAogIGFubm90YXRpb25fbmFtZXNfcm93ID0gRiwKICBjbHVzdGVyX2NvbHMgPSBULAogIGNsdXN0ZXJfcm93cyA9IFQsCiBjbHVzdGVyaW5nX21ldGhvZCA9ICJ3YXJkLkQyIiwKICBnYXBzX3JvdyA9IEZBTFNFLAopCmhlYXRtYXAKYGBgCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCnNldHdkKCIvVXNlcnMva2FybGF2YXNjby9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1NaWNoaWdhblN0YXRlVW5pdmVyc2l0eS9NYW5uaW5nX2xhYi9NZXRhYm9sb21pY3NfbWFzdGl0aXMvZmlndXJlcyIpCmdnc2F2ZShwbG90PWhlYXRtYXAsICJoZWF0bWFwX3BhdGh3YXlzX21hc3RpdGlzLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDUpCgpgYGAKCiMgRGlmZmVyZW50aWFsIGFidW5kYW5jZSBhbmFseXNlcwoKQWdncmVnYXRlIHBoeWxvc2VxIG9iamVjdHMgYnkgdGltZSBwb2ludHMKYGBge3J9CnBoeXNlcV9kYXkxX3dlZWsxIDwtIHN1YnNldF9zYW1wbGVzKHBoeXNlcV9zdWJjbGFzcywgVGltZV90eCVpbiVjKCJEYXkgLTEiLCJXZWVrIDEiKSkKcGh5c2VxX2RheTFfd2VlazkgPC0gc3Vic2V0X3NhbXBsZXMocGh5c2VxX3N1YmNsYXNzLCBUaW1lX3R4JWluJWMoIkRheSAtMSIsIldlZWsgOSIpKQpwaHlzZXFfZGF5MV93ZWVrNSA8LSBzdWJzZXRfc2FtcGxlcyhwaHlzZXFfc3ViY2xhc3MsIFRpbWVfdHglaW4lYygiRGF5IC0xIiwiV2VlayA1IikpCnBoeXNlcV93ZWVrOV81IDwtIHN1YnNldF9zYW1wbGVzKHBoeXNlcV9zdWJjbGFzcywgVGltZV90eCVpbiVjKCJXZWVrIDkiLCJXZWVrIDEiKSkKcGh5c2VxX3dlZWs5XzEgPC0gc3Vic2V0X3NhbXBsZXMocGh5c2VxX3N1YmNsYXNzLCBUaW1lX3R4JWluJWMoIldlZWsgOSIsIldlZWsgNSIpKQpgYGAKCkFnZ3JlZ2F0ZSBwaHlsb3NlcSBvYmplY3RzIGJ5IHRpbWUgcG9pbnRzCmBgYHtyfQpwaHlzZXFfZGF5MSA8LSBzdWJzZXRfc2FtcGxlcyhwaHlzZXFfc3ViY2xhc3MsIFRpbWVfdHglaW4lIkRheSAtMSIpCnBoeXNlcV93ZWVrMSA8LSBzdWJzZXRfc2FtcGxlcyhwaHlzZXFfc3ViY2xhc3MsIFRpbWVfdHglaW4lYygiV2VlayAxIikpCnBoeXNlcV93ZWVrNSA8LSBzdWJzZXRfc2FtcGxlcyhwaHlzZXFfc3ViY2xhc3MsIFRpbWVfdHglaW4lYygiV2VlayA1IikpCnBoeXNlcV93ZWVrOSA8LSBzdWJzZXRfc2FtcGxlcyhwaHlzZXFfc3ViY2xhc3MsIFRpbWVfdHglaW4lYygiV2VlayA5IikpCmBgYAoKRGF5IDAgKG90aGVyIHRpbWUgcG9pbnRzIHdlcmUgZG9uZSBpbiB0aGUgc2FtZSB3YXkpCmBgYHtyfQpwaHlzZXEgPC0gcGh5c2VxX3dlZWs1CmBgYAoKCk1hQXNMaW4yCmBgYHtyIHJlc3VsdHMgPSBGQUxTRX0KbGlicmFyeShNYWFzbGluMikKc2V0d2QoIi9Vc2Vycy9rYXJsYXZhc2NvL0xpYnJhcnkvQ2xvdWRTdG9yYWdlL09uZURyaXZlLU1pY2hpZ2FuU3RhdGVVbml2ZXJzaXR5L01hbm5pbmdfbGFiL01ldGFib2xvbWljc19tYXN0aXRpcy90YWJsZXMvcGF0aHdheXMiKQojIEZvcm1hdGluZyBhYnVuZGFuY2UgdGFibGUgZm9yIE1hQXNMaW4yIAp0YWJsZSA8LSBtZXJnZShwaHlzZXFAdGF4X3RhYmxlLGRhdGEuZnJhbWUob3R1X3RhYmxlKHBoeXNlcSkpLCBieSA9IDApICU+JSByZW1vdmVfcm93bmFtZXMgJT4lIGNvbHVtbl90b19yb3duYW1lcyh2YXI9IlJvdy5uYW1lcyIpCgpmaXRfZGF0YSA9IE1hYXNsaW4yKAogIGlucHV0X2RhdGEgPSBtZXJnZShwaHlzZXFAdGF4X3RhYmxlLGRhdGEuZnJhbWUob3R1X3RhYmxlKHBoeXNlcSkpLCBieSA9IDApICU+JSAKICAgIHJlbW92ZV9yb3duYW1lcyAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKHZhcj0iUm93Lm5hbWVzIikgICU+JSBzZWxlY3QoMTQ6NTMpLAogIGlucHV0X21ldGFkYXRhID0gbWV0YWRhdGEsCiAgb3V0cHV0ID0gJ21hYXNsaW4yX2RheTFfdHJlYXRtZW50JywKICBmaXhlZF9lZmZlY3RzID0gYygnVHJlYXRtZW50JyksCiMgIHJhbmRvbV9lZmZlY3RzID0gYygidGVtcGVyYXR1cmVfQ2Vsc2l1cyIpLAogIG1pbl9wcmV2YWxlbmNlID0gMC4wMSwKICBtaW5fYWJ1bmRhbmNlID0gIDAuMCwKICBzdGFuZGFyZGl6ZSA9IEYKKQpgYGAKCiMgQWdsb21lcmF0aW5nIHBhdGh3YXlzIGF0IHRoZSBTdWJjbGFzcyBsZXZlbApgYGB7cn0KcGh5c2VxX3BhdGggPC0gdGF4X2dsb20ocGh5c2VxX3BhdGh3YXlzLCB0YXhyYW5rID0gIkRlc2NyaXB0aW9uIikKYGBgCgpgYGB7cn0KbGlicmFyeShtaWNyb2JpYWwpCnJmX3RpbWUgPC0gYmlvbWFya2VyKHBoeXNlcT1waHlzZXFfcGF0aCwgZ3JvdXAgPSAiVGltZV90eCIsIG5vcm1hbGl6ZSA9IEYpCnJmX3RpbWUKYGBgCgoKYGBge3IgZmlnLmhlaWdodD0yMH0KcmZfdGltZSAlPiUgaGVhZChuPTI1KSAlPiUgZ2diYXJwbG90KHk9IlZhbHVlIix4PSJEZXNjcmlwdGlvbiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMsIGZpbGwgPSAiQ2xhc3MiLCBwYWxldHRlID0gInNpbXBzb25zIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpCmBgYAoKIyBDb252ZXJ0aW5nIHBoeWxvc2VxIG9iamVjdCB0byBkYXRhZnJhbWUKYGBge3J9CnBoeXNlcV9kZiA8LSBwc21lbHQocGh5c2VxX3BhdGgpCmBgYAoKYGBge3IgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTh9CnRvcDI1IDwtIHJmX3RpbWUgJT4lIGhlYWQobj0yNSkKbWVhbiA8LSBwaHlzZXFfZGYgJT4lIGdyb3VwX2J5KERlc2NyaXB0aW9uKSAlPiUgc3VtbWFyaXNlKEF2ZXJhZ2UgPSBtZWFuKEFidW5kYW5jZSkpCgpvcmRlciA8LSBwaHlzZXFfZGYgJT4lIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uKSAlPiUgbWVyZ2UobWVhbiwgYnk9IkRlc2NyaXB0aW9uIikgJT4lIG11dGF0ZShGQz1BYnVuZGFuY2UvQXZlcmFnZSkgJT4lIGdyb3VwX2J5KFRpbWVfdHgsIERlc2NyaXB0aW9uKSAlPiUgc3VtbWFyaXNlKHRvcCA9IG1lYW4oRkMpKSAlPiUgZmlsdGVyKFRpbWVfdHg9PSJEYXkgLTEiKSAlPiUgYXJyYW5nZSh0b3ApCgp0b3BfMjVfcGxvdCA8LSBwaHlzZXFfZGYgJT4lIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uKSAlPiUgbWVyZ2UobWVhbiwgYnk9IkRlc2NyaXB0aW9uIikgJT4lIG11dGF0ZShGQz1BYnVuZGFuY2UvQXZlcmFnZSkgJT4lIAogIGdnYmFycGxvdCh4PSJEZXNjcmlwdGlvbiIseT0iRkMiLCBmaWxsPSJUaW1lX3R4IiwgcGFsZXR0ZSA9IGMoIiNGRkQ3MDAiLCAiIzAwODAwMCIsICIjMDA3M0MyZmYiLCAiIzgwMDA4MCIpLAogICAgICAgICAgICBhZGQgPSBjKCJtZWFuX2NpIiksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcpLCBvcmllbnRhdGlvbj0iaG9yaXoiLCB4bGFiID0gIiIsIHlsYWIgPSAiRm9sZCBjaGFuZ2UgKG1lYW4pIiwKICAgICAgICAgICAgI2ZhY2V0LmJ5ID0gIkNsYXNzIiwKICAgICAgICAgICAgb3JkZXIgPSBvcmRlciREZXNjcmlwdGlvbikKdG9wXzI1X3Bsb3QKYGBgCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpzZXR3ZCgiL1VzZXJzL2thcmxhdmFzY28vTGlicmFyeS9DbG91ZFN0b3JhZ2UvT25lRHJpdmUtTWljaGlnYW5TdGF0ZVVuaXZlcnNpdHkvTWFubmluZ19sYWIvTWV0YWJvbG9taWNzX21hc3RpdGlzL2ZpZ3VyZXMiKQpnZ3NhdmUocGxvdD10b3BfMjVfcGxvdCwgInRvcDI1X3JmX3BhdGh3YXlzX21hc3RpdGlzLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDgpCmBgYAoKIyBUcmVhdG1lbnQgcGxvdApgYGB7cn0KcGh5c2VxX2RheTEgPC0gc3Vic2V0X3NhbXBsZXMocGh5c2VxX3BhdGgsIFRpbWVfdHglaW4lYygiRGF5IC0xIikpCnBoeXNlcV93ZWVrMSA8LSBzdWJzZXRfc2FtcGxlcyhwaHlzZXFfcGF0aCwgVGltZV90eCVpbiVjKCJXZWVrIDEiKSkKcGh5c2VxX3dlZWs1IDwtIHN1YnNldF9zYW1wbGVzKHBoeXNlcV9wYXRoLCBUaW1lX3R4JWluJWMoIldlZWsgNSIpKQpwaHlzZXFfd2VlazkgPC0gc3Vic2V0X3NhbXBsZXMocGh5c2VxX3BhdGgsIFRpbWVfdHglaW4lYygiV2VlayA5IikpCmBgYAoKYGBge3J9CmxpYnJhcnkobWljcm9iaWFsKQpyZl90cmVhdG1lbnQgPC0gYmlvbWFya2VyKHBoeXNlcT1waHlzZXFfd2VlazksIGdyb3VwID0gIlRyZWF0bWVudCIsIG5vcm1hbGl6ZSA9IEYpCnJmX3RyZWF0bWVudApgYGAKYGBge3IgZmlnLmhlaWdodD0xMH0KcmZfdHJlYXRtZW50ICU+JSBoZWFkKG49MjUpICU+JSBnZ2JhcnBsb3QoeT0iVmFsdWUiLHg9IkRlc2NyaXB0aW9uIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIywgZmlsbCA9ICJDbGFzcyIsIHBhbGV0dGUgPSAic2ltcHNvbnMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9OH0KdG9wMjUgPC0gcmZfdHJlYXRtZW50ICU+JSBoZWFkKG49MjUpCm1lYW4gPC0gcGh5c2VxX2RmICU+JSBmaWx0ZXIoVGltZV90eD09IldlZWsgNSIpICU+JSBncm91cF9ieShEZXNjcmlwdGlvbikgJT4lIHN1bW1hcmlzZShBdmVyYWdlID0gbWVhbihBYnVuZGFuY2UpKQoKb3JkZXIgPC0gcGh5c2VxX2RmICU+JSBmaWx0ZXIoRGVzY3JpcHRpb24gJWluJSB0b3AyNSREZXNjcmlwdGlvbiwgVGltZV90eD09IldlZWsgNSIpICU+JSBtZXJnZShtZWFuLCBieT0iRGVzY3JpcHRpb24iKSAlPiUgbXV0YXRlKEZDPUFidW5kYW5jZS9BdmVyYWdlKSAlPiUgZ3JvdXBfYnkoVHJlYXRtZW50LCBEZXNjcmlwdGlvbikgJT4lIHN1bW1hcmlzZSh0b3AgPSBtZWFuKEZDKSkgJT4lIGZpbHRlcihUcmVhdG1lbnQ9PSJDb250cm9sIikgJT4lIGFycmFuZ2UodG9wKQoKdG9wXzI1X3c1X3Bsb3QgPC0gcGh5c2VxX2RmICU+JSAKICBmaWx0ZXIoRGVzY3JpcHRpb24gJWluJSB0b3AyNSREZXNjcmlwdGlvbiwgVGltZV90eD09IldlZWsgNSIpICU+JSAKICBtZXJnZShtZWFuLCBieT0iRGVzY3JpcHRpb24iKSAlPiUgbXV0YXRlKEZDPUFidW5kYW5jZS9BdmVyYWdlKSAlPiUgCiAgZ2diYXJwbG90KHg9IkRlc2NyaXB0aW9uIiwgeT0iRkMiLCBmaWxsPSJUcmVhdG1lbnQiLCBwYWxldHRlID0gIm5wZyIsCiAgICAgICAgICAgIGFkZCA9IGMoIm1lYW5fY2kiKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNyksIAogICAgICAgICAgICBvcmllbnRhdGlvbj0iaG9yaXoiLCB4bGFiID0gIiIsIHlsYWIgPSAiRm9sZCBjaGFuZ2UgKG1lYW4pIiwKICAgICAgICAgICAgZmFjZXQuYnkgPSAiVGltZV90eCIsCiAgICAgICAgICAgIG9yZGVyID0gb3JkZXIkRGVzY3JpcHRpb24KICAgICAgICAgICAgKQp0b3BfMjVfdzVfcGxvdApgYGAKCmBgYHtyfQpwaHlzZXFfZGYgJT4lIAogIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uLCBUaW1lX3R4PT0iV2VlayA5IikgJT4lIAogIGdyb3VwX2J5KERlc2NyaXB0aW9uKSAlPiUgCiAgd2lsY294X3Rlc3QoQWJ1bmRhbmNlIH4gVHJlYXRtZW50LCBwYWlyZWQgPSBGLCBhbHRlcm5hdGl2ZSA9ICJsZXNzIikgJT4lIAogIGFkZF9zaWduaWZpY2FuY2UoKQpgYGAKCmBgYHtyfQpwaHlzZXFfZGYgJT4lIAogIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uLCBUaW1lX3R4PT0iV2VlayA5IikgJT4lIAogIGdyb3VwX2J5KERlc2NyaXB0aW9uKSAlPiUgCiAgd2lsY294X3Rlc3QoQWJ1bmRhbmNlIH4gVHJlYXRtZW50LCBwYWlyZWQgPSBGLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikgJT4lIAogIGFkZF9zaWduaWZpY2FuY2UoKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD04fQp0b3AyNSA8LSByZl90cmVhdG1lbnQgJT4lIGhlYWQobj0yNSkKbWVhbiA8LSBwaHlzZXFfZGYgJT4lIGZpbHRlcihUaW1lX3R4PT0iV2VlayA5IikgJT4lIGdyb3VwX2J5KERlc2NyaXB0aW9uKSAlPiUgc3VtbWFyaXNlKEF2ZXJhZ2UgPSBtZWFuKEFidW5kYW5jZSkpCgpvcmRlciA8LSBwaHlzZXFfZGYgJT4lIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uLCBUaW1lX3R4PT0iV2VlayA5IikgJT4lIG1lcmdlKG1lYW4sIGJ5PSJEZXNjcmlwdGlvbiIpICU+JSBtdXRhdGUoRkM9QWJ1bmRhbmNlL0F2ZXJhZ2UpICU+JSBncm91cF9ieShUcmVhdG1lbnQsIERlc2NyaXB0aW9uKSAlPiUgc3VtbWFyaXNlKHRvcCA9IG1lYW4oRkMpKSAlPiUgZmlsdGVyKFRyZWF0bWVudD09IkNvbnRyb2wiKSAlPiUgYXJyYW5nZSh0b3ApCgp0b3BfMjVfdzlfcGxvdCA8LSBwaHlzZXFfZGYgJT4lIAogIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uLCBUaW1lX3R4PT0iV2VlayA5IikgJT4lIAogIG1lcmdlKG1lYW4sIGJ5PSJEZXNjcmlwdGlvbiIpICU+JSBtdXRhdGUoRkM9QWJ1bmRhbmNlL0F2ZXJhZ2UpICU+JSAKICBnZ2JhcnBsb3QoeD0iRGVzY3JpcHRpb24iLCB5PSJGQyIsIGZpbGw9IlRyZWF0bWVudCIsIHBhbGV0dGUgPSAibnBnIiwKICAgICAgICAgICAgYWRkID0gYygibWVhbl9jaSIpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSwgCiAgICAgICAgICAgIG9yaWVudGF0aW9uPSJob3JpeiIsIHhsYWIgPSAiIiwgeWxhYiA9ICJGb2xkIGNoYW5nZSAobWVhbikiLAogICAgICAgICAgICBmYWNldC5ieSA9ICJUaW1lX3R4IiwKICAgICAgICAgICAgb3JkZXIgPSBvcmRlciREZXNjcmlwdGlvbgogICAgICAgICAgICApCnRvcF8yNV93OV9wbG90CmBgYAoKYGBge3IgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTh9CnRvcDI1IDwtIHJmX3RyZWF0bWVudCAlPiUgaGVhZChuPTI1KQptZWFuIDwtIHBoeXNlcV9kZiAlPiUgZmlsdGVyKFRpbWVfdHg9PSJXZWVrIDEiKSAlPiUgZ3JvdXBfYnkoRGVzY3JpcHRpb24pICU+JSBzdW1tYXJpc2UoQXZlcmFnZSA9IG1lYW4oQWJ1bmRhbmNlKSkKCm9yZGVyIDwtIHBoeXNlcV9kZiAlPiUgZmlsdGVyKERlc2NyaXB0aW9uICVpbiUgdG9wMjUkRGVzY3JpcHRpb24sIFRpbWVfdHg9PSJXZWVrIDEiKSAlPiUgbWVyZ2UobWVhbiwgYnk9IkRlc2NyaXB0aW9uIikgJT4lIG11dGF0ZShGQz1BYnVuZGFuY2UvQXZlcmFnZSkgJT4lIGdyb3VwX2J5KFRyZWF0bWVudCwgRGVzY3JpcHRpb24pICU+JSBzdW1tYXJpc2UodG9wID0gbWVhbihGQykpICU+JSBmaWx0ZXIoVHJlYXRtZW50PT0iQW50aWJpb3RpYyIpICU+JSBhcnJhbmdlKHRvcCkKCnRvcF8yNV93MV9wbG90IDwtIHBoeXNlcV9kZiAlPiUgCiAgZmlsdGVyKERlc2NyaXB0aW9uICVpbiUgdG9wMjUkRGVzY3JpcHRpb24sIFRpbWVfdHg9PSJXZWVrIDEiKSAlPiUgCiAgbWVyZ2UobWVhbiwgYnk9IkRlc2NyaXB0aW9uIikgJT4lIG11dGF0ZShGQz1BYnVuZGFuY2UvQXZlcmFnZSkgJT4lIAogIGdnYmFycGxvdCh4PSJEZXNjcmlwdGlvbiIsIHk9IkZDIiwgZmlsbD0iVHJlYXRtZW50IiwgcGFsZXR0ZSA9ICJucGciLAogICAgICAgICAgICBhZGQgPSBjKCJtZWFuX2NpIiksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcpLCAKICAgICAgICAgICAgb3JpZW50YXRpb249Imhvcml6IiwgeGxhYiA9ICIiLCB5bGFiID0gIkZvbGQgY2hhbmdlIChtZWFuKSIsCiAgICAgICAgICAgICNmYWNldC5ieSA9ICJDbGFzcyIsCiAgICAgICAgICAgIG9yZGVyID0gb3JkZXIkRGVzY3JpcHRpb24KICAgICAgICAgICAgKQp0b3BfMjVfdzFfcGxvdApgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD04fQp0b3AyNSA8LSByZl90cmVhdG1lbnQgJT4lIGhlYWQobj0yNSkKbWVhbiA8LSBwaHlzZXFfZGYgJT4lIGZpbHRlcihUaW1lX3R4PT0iRGF5IC0xIikgJT4lIGdyb3VwX2J5KERlc2NyaXB0aW9uKSAlPiUgc3VtbWFyaXNlKEF2ZXJhZ2UgPSBtZWFuKEFidW5kYW5jZSkpCgpvcmRlciA8LSBwaHlzZXFfZGYgJT4lIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uLCBUaW1lX3R4PT0iRGF5IC0xIikgJT4lIG1lcmdlKG1lYW4sIGJ5PSJEZXNjcmlwdGlvbiIpICU+JSBtdXRhdGUoRkM9QWJ1bmRhbmNlL0F2ZXJhZ2UpICU+JSBncm91cF9ieShUcmVhdG1lbnQsIERlc2NyaXB0aW9uKSAlPiUgc3VtbWFyaXNlKHRvcCA9IG1lYW4oRkMpKSAlPiUgZmlsdGVyKFRyZWF0bWVudD09IkFudGliaW90aWMiKSAlPiUgYXJyYW5nZSh0b3ApCgp0b3BfMjVfZDFfcGxvdCA8LSBwaHlzZXFfZGYgJT4lIAogIGZpbHRlcihEZXNjcmlwdGlvbiAlaW4lIHRvcDI1JERlc2NyaXB0aW9uLCBUaW1lX3R4PT0iRGF5IC0xIikgJT4lIAogIG1lcmdlKG1lYW4sIGJ5PSJEZXNjcmlwdGlvbiIpICU+JSBtdXRhdGUoRkM9QWJ1bmRhbmNlL0F2ZXJhZ2UpICU+JSAKICBnZ2JhcnBsb3QoeD0iRGVzY3JpcHRpb24iLCB5PSJGQyIsIGZpbGw9IlRyZWF0bWVudCIsIHBhbGV0dGUgPSAibnBnIiwKICAgICAgICAgICAgYWRkID0gYygibWVhbl9jaSIpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSwgCiAgICAgICAgICAgIG9yaWVudGF0aW9uPSJob3JpeiIsIHhsYWIgPSAiIiwgeWxhYiA9ICJGb2xkIGNoYW5nZSAobWVhbikiLAogICAgICAgICAgICAjZmFjZXQuYnkgPSAiQ2xhc3MiLAogICAgICAgICAgICBvcmRlciA9IG9yZGVyJERlc2NyaXB0aW9uCiAgICAgICAgICAgICkKdG9wXzI1X2QxX3Bsb3QKYGBgCgpgYGB7ciBmaWcud2lkdGg9MjB9Cnc1X3c5X2RpZmZfcGxvdHMgPC0gZ2dhcnJhbmdlKHRvcF8yNV93NV9wbG90LCB0b3BfMjVfdzlfcGxvdCwgbGFiZWxzID0gYygiQSIsIkIiKSwgbnJvdz0xLCBjb21tb24ubGVnZW5kID0gVCkKdzVfdzlfZGlmZl9wbG90cwpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCnNldHdkKCIvVXNlcnMva2FybGF2YXNjby9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1NaWNoaWdhblN0YXRlVW5pdmVyc2l0eS9NYW5uaW5nX2xhYi9NZXRhYm9sb21pY3NfbWFzdGl0aXMvZmlndXJlcyIpCmdnc2F2ZShwbG90PXc1X3c5X2RpZmZfcGxvdHMsICJ0b3AyNV9yZl9tZXRhYm9saWNwYXRoc19tYXN0aXRpcy5wbmciLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSA4KQpgYGAKIyBQYXRod2F5cyBkaWZmZXJlbnRpYWwKYGBge3IgZmlnLndpZHRoPTIwfQpwYXRoX2RpZmZfcGxvdHMgPC0gZ2dhcnJhbmdlKHRvcF8yNV93MV9wbG90LHRvcF8yNV93NV9wbG90LCB0b3BfMjVfdzlfcGxvdCwgbGFiZWxzID0gYygiQSIsIkIiLCJDIiksIG5yb3c9MSwgY29tbW9uLmxlZ2VuZCA9IFQpCnBhdGhfZGlmZl9wbG90cwpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCnNldHdkKCIvVXNlcnMva2FybGF2YXNjby9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9PbmVEcml2ZS1NaWNoaWdhblN0YXRlVW5pdmVyc2l0eS9NYW5uaW5nX2xhYi9NZXRhYm9sb21pY3NfbWFzdGl0aXMvZmlndXJlcyIpCmdnc2F2ZShwbG90PXBhdGhfZGlmZl9wbG90cywgInRvcF9yZl9tZXRhYm9saWNwYXRoc19tYXN0aXRpcy5wbmciLCB3aWR0aCA9IDI0LCBoZWlnaHQgPSA4KQpgYGA=